package com.aididi.designpatter;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Auther: zx.xu
 * @Description:    策略模式
 * 在策略模式中，可以在运行时更改类行为或其算法。 这种类型的设计模式属于行为型模式。
 * 在策略模式中，创建表示各种策略对象和其行为根据其策略对象而变化的上下文对象。 策略对象更改上下文对象的执行算法。
 */
public class StrategyPatternDemo {

    public static void main(String[] args) {
        Context context = new Context(new OperationAdd());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationSubstract());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationMultiply());
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));

        //  策略模式 + 工厂模式  优化if-else
        //Strategy strategy = StrategyFactory.getByStrategyType(new OperationAdd());
        //strategy.doOperation(10,5);

    }

}

//创建一个接口
interface Strategy {
    public int doOperation(int num1, int num2);

}

//创建三个实现相同接口的具体类
 class OperationAdd implements Strategy{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

class OperationSubstract implements Strategy{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

class OperationMultiply implements Strategy{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}

//创建上下文（Context ）类
class Context {
    private Strategy strategy;

    public Context(Strategy strategy){
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2){
        return strategy.doOperation(num1, num2);
    }
}


//创建三个实现相同接口的具体类
class OperationAdd2 implements Strategy,InitializingBean{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyFactory.register("operationAdd",this);
    }
}

class OperationSubstract2 implements Strategy,InitializingBean{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyFactory.register("operationSubstract",this);
    }
}

class OperationMultiply2 implements Strategy,InitializingBean {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyFactory.register("operationMultiply",this);
    }
}

//为了方便我们从Spring中获取Strategy的各个策略类，我们创建一个工厂类
class StrategyFactory {
    private static Map<String,Strategy> services = new ConcurrentHashMap<String,Strategy>();

    public static Strategy getByStrategyType(Strategy strategy){
        return services.get(strategy);
    }

    public static void register(String userType,Strategy strategy) {
        Assert.notNull(userType, "userType can't be null");
        services.put(userType, strategy);
    }
}
